package jal4eclipse.jal;

import jal4eclipse.jal.structure.JContainer;
import jal4eclipse.jal.structure.JElement;
import jal4eclipse.jal.structure.JInclude;
import jal4eclipse.jal.structure.JMethod;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public final class JALParser {
	private JALParser() {}
	/**
	 * Build a structure representing the file
	 * this is useful to file an outline view
	 * @param text
	 * @return
	 */
	public static JContainer getFileStructure(String text) {
		JContainer root = new JContainer("root");
		JContainer inc = new JContainer("includes");
		JContainer methods = new JContainer("methods");
		root.addElement(inc);
		root.addElement(methods);
		
		String[]lines = text.split("\n");
		for (int i = 0;i<lines.length;i++) {
			String line = lines[i];
			line = line.trim();
			String upperLine = line.toUpperCase();
			if (upperLine.startsWith("INCLUDE ")) {
				JInclude el = new JInclude(line.substring("INLCUDE ".length()));
				inc.addElement(el);
			} else if (upperLine.startsWith("PROCEDURE ")) {
				String name = line.substring("PROCEDURE ".length());
				name = prepareName(name);
				
				JMethod el = new JMethod(name);
				try {el.setParams(line.substring(line.indexOf('(')+1,line.indexOf(')')));}catch (Exception e){}
				methods.addElement(el);
			} else if (upperLine.startsWith("FUNCTION ")) {
				String name = line.substring("FUNCTION ".length());
				name = prepareName(name);
				JMethod el = new JMethod(name);
				try {el.setParams(line.substring(line.indexOf('(')+1,line.indexOf(')')));}catch (Exception e){}
				methods.addElement(el);
			} 
		}
		return root;
	}
	
	private static String prepareName(String name) {
		
		int pos = name.indexOf(' ');
		if (pos >= 0) {
			name = name.substring(0,pos);
		}
		pos = name.indexOf('(');
		if (pos >= 0) {
			name = name.substring(0,pos);
		}
		return name.trim();
	}
	/**
	 * 
	 * @param file
	 * @return
	 */
	
	public static JContainer getFileStructure(File file) {
		BufferedReader reader=null;
		try {
			reader = new BufferedReader(new FileReader(file));
		} catch (FileNotFoundException e1) {
			
			e1.printStackTrace();
		}
		StringBuffer buf = new StringBuffer();
		String line="";
		try {
			while ((line=reader.readLine()) != null){
				buf.append(line+"\n");
			}
		} catch (IOException e) {
			
			e.printStackTrace();
		} finally{
			try {
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return getFileStructure(buf.toString());
	}
	
	
	
	
	
	
	/**
	 * Determine if the file is a "main" file, ie a file taht is a potential target for
	 * the JAL compiler
	 * @param filename
	 * @return true is the file is a "main" file containing a forever loop
	 */
	public static boolean isMainFile(String filename) {
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(filename));
			String line ="";
			while( (line = reader.readLine())!= null) {
				try {line = line.split(";")[0];} catch (Exception e) {}
				try {line = line.split("--")[0];} catch (Exception e) {}
				line = line.toUpperCase();
				line = line.trim();
				if (line.equals("FOREVER LOOP")) {
					return true;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (reader != null ) {
				try {
					reader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}
	
	/**
	 * Build a map wich contains availbale methods for a file,
	 * with method as key and method_file as value 
	 * @param file
	 * @includeMap all includes (including sub includes) for the file
	 * @param map the map that will be filled
	 */
	public static void buildTree(File file,Map includesMap,Map map){
		
		JContainer st = JALParser.getFileStructure(file);
		
		List elems = (List)st.getElements();
		for (Iterator it = elems.iterator();it.hasNext();){
			JElement elem = (JElement) it.next();
		
			if (elem instanceof JContainer) {
				JContainer container = (JContainer) elem;
				if ("includes".equals(elem.getName())) {
					for (Iterator itCont = container.getElements().iterator();itCont.hasNext();){
						JElement inc = (JElement) itCont.next();	
						String incName = (String)includesMap.get(inc.getName().toLowerCase());
						if (incName == null) {
							System.out.println("unknown file : "+inc.getName());
						} else {
							//System.out.println(inc.getName()+" - "+incName );
							File f = new File(incName);
							buildTree(f,includesMap,map);
						}
					}
				} else if ("methods".equals(elem.getName())) {
					for (Iterator itCont = container.getElements().iterator();itCont.hasNext();){
						JElement el = (JElement) itCont.next();
						String name = el.getName();
						
						// _name are private... don't show pseudo met 'get and 'put
						if((! name.startsWith("_")) &&(name.indexOf('\'')==-1)){
							el.setFilename(file.getAbsolutePath());
							map.put(el.getName(), el);	
						}
					}
				}
			} else{
				map.put(elem.getName(), file.getAbsolutePath());

			}

		}
	}
	
}
